package org.jeecg.modules.payment;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.ReflectUtil;
import lombok.extern.slf4j.Slf4j;
import net.sourceforge.tess4j.TesseractException;
import org.jeecg.modules.payment.paymentalipayaccounts.entity.PaymentAlipayAccounts;
import org.jeecg.modules.payment.paymentalipayaccounts.service.IPaymentAlipayAccountsService;
import org.jeecg.modules.payment.paymentalipayorder.entity.PaymentAlipayOrder;
import org.jeecg.modules.payment.paymentalipayorder.service.IPaymentAlipayOrderService;
import org.jeecg.modules.quartz.job.CallbackQuartzJobBean;
import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.net.URL;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Slf4j
@Component
public class PaymentConfiguration implements ApplicationRunner {
    public static ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();

    static {
        threadPoolTaskExecutor.initialize();
    }

    @Autowired
    private ResourceLoader resourceLoader;
    @Autowired
    private IPaymentAlipayAccountsService paymentAlipayAccountsService;
    @Autowired
    private IPaymentAlipayOrderService paymentAlipayOrderService;
    @Autowired
    private RedisTemplate redisTemplate;
    @Value("${jeecg.chromeDriverPath}")
    private String chromeDriverPath;

    public static void main(String[] args) throws IOException, TesseractException, InterruptedException {

//        WebElement element = chromeDriver.findElement(By.cssSelector("#J-checkcode-img"));
//        File screenshot = ((TakesScreenshot)chromeDriver).getScreenshotAs(OutputType.FILE);
//
//        // Get entire page screenshot
//        BufferedImage fullImg= ImageIO.read(screenshot);
//        // Get the location of element on the page
//        org.openqa.selenium.Point point= element.getLocation();
//        // Get width and height of the element
//        int eleWidth= element.getSize().getWidth();
//        int eleHeight= element.getSize().getHeight();
//        // Crop the entire page screenshot to get only element screenshot
//        BufferedImage eleScreenshot= fullImg.getSubimage(point.getX()+282, point.getY()+90, eleWidth, eleHeight);
//        ITesseract instance = new Tesseract();
//        File tessDataFolder = LoadLibs.extractTessResources("tessdata");
//        instance.setDatapath(tessDataFolder.getAbsolutePath()); //相对目录，这个时候tessdata目录和src目录平级
//        instance.setLanguage("eng");
//
//        String result = instance.doOCR(eleScreenshot);
//        ImageIO.write(eleScreenshot,"png",new File("D:\\opt\\upFiles\\test.png"));
//        System.out.println(result);//打印图片内容

    }
   public  static ChromeOptions chromeOptions;
    @Override
    public void run(ApplicationArguments args) throws Exception {
        Resource resource = resourceLoader.getResource("classpath:chrome/chromedriver.exe");
        URL url = getClass().getResource("");
        String protocol = url.getProtocol();
        if ("jar".equals(protocol)) {
            System.setProperty("webdriver.chrome.driver",chromeDriverPath);
        } else if ("file".equals(protocol)) {
            System.setProperty("webdriver.chrome.driver", resource.getFile().getAbsolutePath());
        }else{
            System.setProperty("webdriver.chrome.driver", resource.getFile().getAbsolutePath());
        }

        chromeOptions = new ChromeOptions();
        chromeOptions.setExperimentalOption("excludeSwitches", Collections.singletonList("enable-automation"));
        chromeOptions.setExperimentalOption("useAutomationExtension", false);
        chromeOptions.addArguments("--disable-blink-features=AutomationControlled");
        List<PaymentAlipayAccounts> list = paymentAlipayAccountsService.list();
        list.parallelStream().forEach(paymentAlipayAccounts -> {
            runChromeDriver(chromeOptions, paymentAlipayAccounts,paymentAlipayAccountsService,paymentAlipayOrderService,redisTemplate);
        });


    }

    public static void runChromeDriver(ChromeOptions chromeOptions, PaymentAlipayAccounts paymentAlipayAccounts,IPaymentAlipayAccountsService  paymentAlipayAccountsService,IPaymentAlipayOrderService paymentAlipayOrderService,RedisTemplate redisTemplate) {
        threadPoolTaskExecutor.execute(() -> {
            ChromeDriver chromeDriver = new ChromeDriver(chromeOptions);//最大化窗口
            try {
                chromeDriver.manage().window().maximize();
                chromeDriver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS);
                // get()打开一个站点
                chromeDriver.get("https://auth.alipay.com/login/index.htm");

                Thread.sleep(2000);
                chromeDriver.findElement(By.cssSelector("#J-loginMethod-tabs > li:nth-child(2)")).click();
                Thread.sleep(2000);
                for (char chars : paymentAlipayAccounts.getAccounts().toCharArray()) {
                    Thread.sleep(RandomUtil.randomInt(300, 500));
                    chromeDriver.findElement(By.xpath("//*[@id=\"J-input-user\"]")).sendKeys(String.valueOf(chars));
                }
                Thread.sleep(RandomUtil.randomInt(500, 800));
                for (char chars : paymentAlipayAccounts.getPassword().toCharArray()) {
                    Thread.sleep(RandomUtil.randomInt(300, 500));
                    chromeDriver.findElement(By.xpath("//*[@id=\"password_rsainput\"]")).sendKeys(String.valueOf(chars));
                }
                Thread.sleep(RandomUtil.randomInt(500, 1000));
                chromeDriver.findElement(By.xpath("//*[@id=\"J-login-btn\"]")).click();
                Thread.sleep(5 * 1000);
                while (chromeDriver.getCurrentUrl().contains("https://authet2.alipay.com/login/index.htm")) {
                    for (char chars : paymentAlipayAccounts.getPassword().toCharArray()) {
                        Thread.sleep(RandomUtil.randomInt(300, 500));
                        chromeDriver.findElement(By.xpath("//*[@id=\"password_rsainput\"]")).sendKeys(String.valueOf(chars));
                    }
                    Thread.sleep(RandomUtil.randomInt(500, 1000));
                    chromeDriver.findElement(By.xpath("//*[@id=\"J-login-btn\"]")).click();
                    Thread.sleep(2 * 1000);
                }
                boolean isNext = false;
                while (true) {
                    PaymentAlipayAccounts one = paymentAlipayAccountsService.getOne(paymentAlipayAccountsService.lambdaQuery().eq(PaymentAlipayAccounts::getAccounts, paymentAlipayAccounts.getAccounts()).getWrapper());
                    if (one == null || !one.getPassword().equals(paymentAlipayAccounts.getPassword())) {
                        throw new InterruptedException();
                    }
                    if (isNext) {
                        chromeDriver.findElementByXPath("//*[@id=\"root\"]/div/div/div/div[4]/div[2]/div[2]/div/div/div/ul/li[4]").click();
                    } else {
                        Thread.sleep(60 * 1000);
                        chromeDriver.get("https://mbillexprod.alipay.com/enterprise/fundAccountDetail.htm#/");
                        chromeDriver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS);
                        //切换为最近7天
                        try {
                            chromeDriver.findElementByXPath("//*[@id=\"root\"]/div/div/div/div[2]/div/div/form/div[1]/div[2]/div[2]/div/span/div/div[2]/div[3]").click();
                        }catch (org.openqa.selenium.NoSuchElementException noSuchElementException){
                            continue;
                        }
                        Thread.sleep(3000);
                        try {
                            WebElement elementByXPath = chromeDriver.findElementByXPath("//*[@id=\"root\"]/div/div/div/div[4]/div[1]/div/div/div/div/div[1]/div/div/div[1]/div/span");
                        } catch (org.openqa.selenium.NoSuchElementException noSuchElementException) {
                            continue;
                        }
                        chromeDriver.findElementByXPath("//*[@id=\"root\"]/div/div/div/div[4]/div[2]/div[1]/div[1]/div[2]/div/div/div/div[1]/div[2]").click();
                    }
                    Thread.sleep(RandomUtil.randomInt(2000, 3000));
                    WebElement tbody = chromeDriver.findElementByXPath("//*[@id=\"root\"]/div/div/div/div[4]/div[2]/div[2]/div/div/div/div/div/div[1]/div/table/tbody");
                    List<WebElement> tr = tbody.findElements(By.tagName("tr"));
                    Stream<ConcurrentHashMap> concurrentHashMapStream = tr.stream().map(webElement -> {
                        List<WebElement> elements = webElement.findElements(By.tagName("td"));
                        //入账时间
                        String entryTime = elements.get(0).findElement(By.tagName("span")).findElement(By.tagName("span")).getText();
                        //支付宝交易单号
                        String serialNumber = elements.get(1).findElement(By.tagName("span")).findElement(By.tagName("span")).findElement(By.tagName("span")).getAttribute("title");
                        //商家订单号
                        String orderNumber = new String();
                        try {
                            orderNumber = elements.get(2).findElement(By.tagName("span")).findElement(By.tagName("span")).findElement(By.tagName("span")).getAttribute("title");
                        } catch (org.openqa.selenium.NoSuchElementException noSuchElementException) {

                        }
                        //对方信息
                        String otherInfo = elements.get(3).findElement(By.tagName("div")).getText();
                        //财务类型
                        String financialType = elements.get(4).findElement(By.tagName("span")).findElement(By.tagName("span")).getText();
                        //收支金额
                        String amount = elements.get(5).findElement(By.tagName("span")).findElement(By.tagName("span")).getText();
                        //账户余额
                        String balance = elements.get(6).findElement(By.tagName("span")).findElement(By.tagName("span")).getText();
                        //备注
                        //  String remark = elements.get(7).findElement(By.tagName("span")).findElement(By.tagName("span")).getText();
                        ConcurrentHashMap concurrentHashMap = new ConcurrentHashMap();
                        concurrentHashMap.put("entryTime", entryTime);
                        concurrentHashMap.put("serialNumber", serialNumber);
                        concurrentHashMap.put("orderNumber", orderNumber);
                        concurrentHashMap.put("otherInfo", otherInfo);
                        concurrentHashMap.put("financialType", financialType);
                        concurrentHashMap.put("amount", amount);
                        concurrentHashMap.put("balance", balance);
                        // concurrentHashMap.put("remark", remark);
                        return concurrentHashMap;
                    });
                    List<ConcurrentHashMap> collect = concurrentHashMapStream.collect(Collectors.toList());
                    ConcurrentHashMap concurrentHashMapLast = collect.get(collect.size() - 1);
                    LocalDateTime entryTime = DateUtil.parseLocalDateTime((CharSequence) concurrentHashMapLast.get("entryTime"), DatePattern.NORM_DATETIME_PATTERN);
                    boolean flag = false;
                    for (ConcurrentHashMap concurrentHashMap : collect) {
                        Set<Map.Entry> set = concurrentHashMap.entrySet();
                        set.forEach(entry -> {
                            System.out.printf(entry.getKey() + ":" + entry.getValue() + "   ");
                        });
                        System.out.println();
                        PaymentAlipayOrder paymentAlipayOrder = new PaymentAlipayOrder();
                        set.parallelStream().forEach(entry -> {
                            ReflectUtil.setFieldValue(paymentAlipayOrder, (String) entry.getKey(), entry.getValue());
                        });
                        if (!paymentAlipayOrder.getFinancialType().equals("转账")) {
                            continue;
                        }
                        //推送消息
                        PaymentAlipayOrder paymentAlipayOrderDb = paymentAlipayOrderService.getOne(paymentAlipayOrderService.lambdaQuery().eq(PaymentAlipayOrder::getSerialNumber, paymentAlipayOrder.getSerialNumber()).getWrapper());
                        if (paymentAlipayOrderDb == null) {
                            paymentAlipayOrder.setState("N");
                            paymentAlipayOrder.setCallbackNum(0);
                            paymentAlipayOrder.setSecretKey(paymentAlipayAccounts.getSecretKey());
                            paymentAlipayOrder.setCallbackUrl(paymentAlipayAccounts.getCallbackUrl());
                            paymentAlipayOrder.setAccounts(paymentAlipayAccounts.getAccounts());
                            paymentAlipayOrder.setPid(paymentAlipayAccounts.getPid());
                            paymentAlipayOrderService.save(paymentAlipayOrder);
                            //推送消息
                            redisTemplate.opsForZSet().add(CallbackQuartzJobBean.CALLBACK_QUEUE, paymentAlipayOrder, System.currentTimeMillis());
                        } else {
                            flag = true;
                            break;
                        }
                    }
                    String attribute = chromeDriver.findElementByXPath("//*[@id=\"root\"]/div/div/div/div[4]/div[2]/div[2]/div/div/div/ul/li[4]").getAttribute("aria-disabled");
                    if (attribute==null&&!flag && paymentAlipayAccounts.getCreateTime().before(Date.from(entryTime.toInstant(ZoneOffset.ofHours(8))))) {
                        isNext = true;
                    } else {
                        isNext = false;
                    }


                }
            } catch (Exception e) {
                log.error("爬虫------------------------------------------------", e);
                chromeDriver.quit();
            }

        });
    }

}
